package br.fagoc.easyds.datastructure;

import br.fagoc.easyds.exception.ElementNotFoundException;
import br.fagoc.easyds.exception.EmptyStructureException;
import br.fagoc.easyds.exception.FullStructureException;
import br.fagoc.easyds.exception.LimiteExcedidoException;
import br.fagoc.easyds.ui.code.TextAreaController;
import br.fagoc.easyds.ui.jgraph.GraphCellManipulator;
import br.fagoc.easyds.ui.jgraph.GraphEdgeManipulator;
import br.fagoc.easyds.ui.jgraph.GraphManipulator;

import com.mxgraph.model.mxCell;
import com.mxgraph.view.mxGraph;

public class StaticList {
	private final double CELULA_LARGURA = 80;
	private final double CELULA_ALTURA = 50;
	private final double EIXO_X_ORIGEM = 0;
	private final double EIXO_Y_ORIGEM = 100;
	private final double EIXO_X_DESTINO = 20;
	private final double EIXO_Y_DESTINO = 20;
	private final double EIXO_X_LIMITE_REMOCAO = 0 - CELULA_LARGURA;
	private final double EIXO_Y_LIMITE_REMOCAO = 100;
	private final double MODIFICADOR_EIXO_X = 82;

	private GraphManipulator graphManipulator;
	private GraphCellManipulator graphCellManipulator;
	private GraphEdgeManipulator graphEdgeManipulator;
	
	private mxCell[] list;
	private int maximumLength;
	private int length = 0;
	private TextAreaController taController;
	
	public StaticList(mxGraph graph, TextAreaController taController, int size){
		this.graphManipulator = new GraphManipulator(graph);
		this.graphCellManipulator = new GraphCellManipulator(graph);
		this.graphEdgeManipulator = new GraphEdgeManipulator(graph);

		list = new mxCell[size];
		this.maximumLength = size;

		this.taController = taController;
		initializeStructure();
	}
	
	public void initializeStructure(){
		for(int i = 0; i < maximumLength; i++){
			list[i] = graphCellManipulator.createRectangularCell("", EIXO_X_DESTINO + (i * MODIFICADOR_EIXO_X), EIXO_Y_DESTINO);
			graphCellManipulator.drawCell(list[i]);
		}
		
		taController.showText("/br/fagoc/easyds/file/ListaDupla.txt");
	}
	
	public void inserirComeco(String value) throws FullStructureException{
		if(length == maximumLength){
			throw new FullStructureException();
		}
		else{
			taController.markText(177, 694);
			
			mxCell cell = list[0];
			graphCellManipulator.blinkCell(cell);
			
			for(int i = length-1; i >= 0; i--){
				list[i+1].setValue(list[i].getValue().toString());
			}
			
			cell.setValue(value);
			length++;
			
			for(int i = 0; i < length; i++){
				graphCellManipulator.drawCell(list[i]);
			}
		}
	}
	
	public void inserirFim(String value) throws FullStructureException{
		if(length == maximumLength){
			throw new FullStructureException();
		}
		else{
			taController.markText(696, 1280);
			
			mxCell cell = list[length];
			
			graphCellManipulator.blinkCell(cell);
			
			cell.setValue(value);
			graphCellManipulator.drawCell(cell);
			
			length++;
		}
	}
	
	public void inserirNaPosicao(int position, String value) throws FullStructureException, LimiteExcedidoException{
		if(length == maximumLength){
			throw new FullStructureException();
		}
		else if(position < 0 || position >= maximumLength){
			throw new LimiteExcedidoException(position, 0, maximumLength-1);
		}
		else{
			taController.markText(1283, 2098);
			
			mxCell cell = list[position];
			
			for(int i = length-1; i >= position; i--){
				list[i+1].setValue(list[i].getValue().toString());
			}
			
			cell.setValue("");
			
			for(int i = 0; i < maximumLength; i++){
				graphCellManipulator.drawCell(list[i]);
			}

			graphCellManipulator.blinkCell(cell);
			cell.setValue(value);
			graphCellManipulator.drawCell(cell);
			
			length++;
		}
	}
	
	public void removerComeco() throws EmptyStructureException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			taController.markText(2101, 2464);
			
			mxCell cell = list[0];
			graphCellManipulator.blinkCell(cell);
			
			for(int i = 0; i < length-1; i++){
				list[i].setValue(list[i+1].getValue().toString());
			}
			
			list[length-1].setValue("");
			graphCellManipulator.drawCell(list[length-1]);
			length--;
			
			for(int i = 0; i < length; i++){
				graphCellManipulator.drawCell(list[i]);
			}
		}
	}
	
	public void removerFim() throws EmptyStructureException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			taController.markText(2467, 3073);
			
			mxCell cell = list[length-1];
			
			graphCellManipulator.blinkCell(cell);
			
			cell.setValue("");
			graphCellManipulator.drawCell(cell);
			
			length--;
		}
	}
	
	public void removerNaPosicao(int position) throws EmptyStructureException, LimiteExcedidoException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else if(position < 0 || position >= length){
			throw new LimiteExcedidoException(position, 0, length-1);
		}
		else{
			taController.markText(3076, 3833);
			
			mxCell cell = list[position];
			graphCellManipulator.blinkCell(cell);
			
			for(int i = position; i < length-1; i++){
				list[i].setValue(list[i+1].getValue());
			}
			
			list[length-1].setValue("");
			
			for(int i = 0; i < length; i++){
				graphCellManipulator.drawCell(list[i]);
			}
			
			length--;
		}
	}
	
	public void removerPeloValor(String value) throws EmptyStructureException, ElementNotFoundException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			mxCell cell = null;
			int position = 0;
			
			for(int i = 0; i < length; i++){
				graphCellManipulator.blinkCell(list[i]);
				
				if(value.equals(list[i].getValue().toString())){
					cell = list[i];
					position = i;
					break;
				}
			}
			
			if(cell == null){
				throw new ElementNotFoundException(value);
			}
			else{
				for(int i = position; i < length-1; i++){
					list[i].setValue(list[i+1].getValue());
				}
				
				list[length-1].setValue("");
				
				for(int i = 0; i < length; i++){
					graphCellManipulator.drawCell(list[i]);
				}
				
				length--;
			}
		}
	}
	
	public void buscarComeco() throws EmptyStructureException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			taController.markText(4156, 4285);
			
			mxCell cell = list[0];
			graphCellManipulator.blinkCell(cell);
		}
	}
	
	public void buscarFim() throws EmptyStructureException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			taController.markText(4287, 4514);
			
			mxCell cell = list[length-1];
			graphCellManipulator.blinkCell(cell);
		}
	}
	
	public void buscarNaPosicao(int position) throws EmptyStructureException, LimiteExcedidoException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else if(position < 0 || position >= length){
			throw new LimiteExcedidoException(position, 0, length-1);
		}
		else{
			taController.markText(3836, 4153);
			
			mxCell cell = list[position];
			graphCellManipulator.blinkCell(cell);
		}
	}
	
	public void buscarPeloValor(String value) throws EmptyStructureException, ElementNotFoundException{
		if(length == 0){
			throw new EmptyStructureException();
		}
		else{
			mxCell cell = null;
			
			for(int i = 0; i < length; i++){
				graphCellManipulator.blinkCell(list[i]);
				if(value.equals(list[i].getValue().toString())){
					cell = list[i];
					break;
				}
			}
			
			if(cell == null){
				throw new ElementNotFoundException(value);
			}
			else{
				graphCellManipulator.blinkCell(cell);
			}
		}
	}
}
